/**
 @file sys_usw_internal_port.c

 @date 2010-03-29

 @version v2.0

*/

/****************************************************************************
 *  current queue allocation scheme (Alt + F12 for pretty):
 *
 *           type          port id    channel id      queue number    queue id range
 *     ----------------  ----------   ----------      ------------    --------------
 *      internal port     64 - 191       X              4 * 128        708 - 1219

 ****************************************************************************/

/****************************************************************************
 *
 * Header Files
 *
 ****************************************************************************/

#include "ctc_debug.h"
#include "ctc_macro.h"
#include "ctc_error.h"
#include "ctc_vector.h"
#include "ctc_const.h"

#include "sys_usw_common.h"
#include "sys_usw_chip.h"
#include "sys_usw_ftm.h"
#include "sys_usw_opf.h"
#include "sys_usw_port.h"
#include "sys_usw_internal_port.h"
#include "sys_usw_wb_common.h"
#include "sys_usw_dmps.h"
#include "sys_usw_register.h"
#include "drv_api.h"

/****************************************************************************
 *
 * Global and Declaration
 *
 ****************************************************************************/
sys_inter_port_master_t* inter_port_master[CTC_MAX_LOCAL_CHIP_NUM_PP] = {NULL};
#define SYS_INTERNAL_PORT_INIT_CHECK() \
    do { \
        LCHIP_CHECK(lchip); \
        if (inter_port_master[lchip] == NULL){ \
            SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " Feature not initialized \n");\
			return CTC_E_NOT_INIT;\
 } \
    } while (0)

enum sys_usw_internal_port_op_type_e
{
    SYS_USW_INTERNAL_PORT_OP_TYPE_SET = 1,
    SYS_USW_INTERNAL_PORT_OP_TYPE_FREE,
    SYS_USW_INTERNAL_PORT_OP_TYPE_ALLOC,
    SYS_USW_INTERNAL_PORT_OP_TYPE_NUM = SYS_USW_INTERNAL_PORT_OP_TYPE_ALLOC
};
typedef enum sys_usw_internal_port_op_type_e sys_usw_internal_port_op_type_t;

struct sys_internal_port_type_map_s
{
    uint16 port_id;
    uint16 chan_id;
    uint8 port_num;
    uint8 is_pp;
    uint8 bypass_ipe;
    uint8 bypass_epe;
    uint8 chip_bitmap;
};
typedef struct sys_internal_port_type_map_s sys_internal_port_type_map_t;

extern sys_port_api_master_t* p_usw_port_api_master[CTC_MAX_LOCAL_CHIP_NUM_PP];
#define SYS_PORT_LOCK(lchip) \
    if(p_usw_port_api_master[lchip]->p_port_mutex) sal_mutex_lock(p_usw_port_api_master[lchip]->p_port_mutex)

#define SYS_PORT_UNLOCK(lchip) \
    if(p_usw_port_api_master[lchip]->p_port_mutex) sal_mutex_unlock(p_usw_port_api_master[lchip]->p_port_mutex)

#define SYS_INTERNAL_PORT_NUM        (SYS_INTERNAL_PORT_END - SYS_INTERNAL_PORT_START +  1)

#define SYS_INTERNAL_PORT_SET(lchip, dir, port)   CTC_BIT_SET(inter_port_master[lchip]->is_used[dir][(port)/BITS_NUM_OF_WORD], (port)% BITS_NUM_OF_WORD)
#define SYS_INTERNAL_PORT_UNSET(lchip, dir, port) CTC_BIT_UNSET(inter_port_master[lchip]->is_used[dir][(port)/BITS_NUM_OF_WORD], (port)% BITS_NUM_OF_WORD)
#define SYS_INTERNAL_PORT_ISSET(lchip, dir, port) CTC_IS_BIT_SET(inter_port_master[lchip]->is_used[dir][(port)/BITS_NUM_OF_WORD], (port)% BITS_NUM_OF_WORD)
#define SYS_INTERNAL_PORT_GET(lchip, idx1, idx2)  (idx1*BITS_NUM_OF_WORD+idx2)

extern int32 _sys_usw_internal_port_allocate(uint8 lchip, ctc_internal_port_assign_para_t* p_port_assign, sys_nh_info_dsnh_t* p_dsnh_info);
extern int32 _sys_usw_internal_port_release(uint8 lchip, ctc_internal_port_assign_para_t* p_port_assign);

/****************************************************************************
 *
 * Function
 *
 ****************************************************************************/
#define __________INTERNAL_FUNCTION__________

STATIC int32
_sys_usw_internal_port_set_channel(uint8 lchip, sys_port_chan_map_param_t* p_chan_map_param, ctc_internal_port_type_t type, uint8 is_bind)
{
    uint16 chan_id = 0;
    sys_internal_port_info_t inter_port_info;

    sal_memset(&inter_port_info, 0, sizeof(sys_internal_port_info_t));
    if (CTC_INTERNAL_PORT_TYPE_ILOOP == type)
    {
        chan_id = MCHIP_CAP(SYS_CAP_CHANID_ILOOP);
    }
    else if (CTC_INTERNAL_PORT_TYPE_ELOOP == type ||CTC_INTERNAL_PORT_TYPE_ILOOP_ELOOP == type)
    {
		if (DRV_FROM_AT(lchip))
		{
			chan_id = is_bind?p_chan_map_param->channel_id:SYS_DMPS_INVALID_CHAN_ID;
            inter_port_info.chan_id = chan_id;
            inter_port_info.pp_id = is_bind?(p_chan_map_param->channel_id - MCHIP_CAP(SYS_CAP_CHANID_ELOOP))>>1:0;
            inter_port_info.lport = p_chan_map_param->lport;
            inter_port_info.port_type = is_bind?SYS_DMPS_ELOOP_PORT:SYS_DMPS_RSV_PORT;
            inter_port_info.sub_chan_id = is_bind?SYS_DMPS_LOOP_SUB_CHAN:SYS_DMPS_INVALID_SUB_CHAN_ID;
            inter_port_info.dp_id = 0;
            inter_port_info.speed_mode = is_bind?0:CTC_PORT_SPEED_MAX;
            inter_port_info.is_update = 1;
            CTC_ERROR_RETURN(sys_usw_dmps_db_set_internal_port_info(lchip, &inter_port_info));
		}
        else if (DRV_FROM_TMM(lchip))
        {
            chan_id = (p_chan_map_param->lport%2)?MCHIP_CAP(SYS_CAP_CHANID_ELOOP):MCHIP_CAP(SYS_CAP_CHANID_ELOOP)+MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM);
        }
        else
        {
            chan_id = MCHIP_CAP(SYS_CAP_CHANID_ELOOP);
        }
    }
    else if (CTC_INTERNAL_PORT_TYPE_FWD == type)
    {
        chan_id = p_chan_map_param->channel_id;
    }
    else
    {
        /* CTC_INTERNAL_PORT_TYPE_DISCARD */
        chan_id = MCHIP_CAP(SYS_CAP_CHANID_DROP);
    }

    if (is_bind)
    {
        CTC_ERROR_RETURN(sys_usw_add_port_to_channel(lchip, p_chan_map_param->lport, chan_id, p_chan_map_param->is_pp));
    }
    else
    {
        CTC_ERROR_RETURN(sys_usw_remove_port_from_channel(lchip, p_chan_map_param->lport, chan_id));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_port_set_port_bitmap(uint8 lchip, ctc_internal_port_assign_para_t* p_port_assign, uint8 op_type)
{

    uint8  igs_set = 0;
    uint8  egs_set = 0;
    uint16 lport = p_port_assign->inter_port;

    igs_set = ((SYS_INTERNAL_PORT_ISSET(lchip, SYS_INTERNAL_PORT_DIR_IGS, SYS_MAP_DRV_LPORT_TO_SYS_LPORT(lport))
                && ((CTC_INTERNAL_PORT_TYPE_FWD == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_ILOOP == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_DISCARD == p_port_assign->type)
                || (CTC_INTERNAL_PORT_TYPE_ILOOP_ELOOP == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_WLAN == p_port_assign->type))) || (SYS_INTERNAL_PORT_ISSET(lchip, SYS_INTERNAL_PORT_DIR_IGS, SYS_MAP_DRV_LPORT_TO_SYS_LPORT(lport+1))
                && (CTC_INTERNAL_PORT_TYPE_WLAN == p_port_assign->type)));


    egs_set = SYS_INTERNAL_PORT_ISSET(lchip, SYS_INTERNAL_PORT_DIR_EGS, p_port_assign->inter_port)
                && ((CTC_INTERNAL_PORT_TYPE_FWD == p_port_assign->type)||(CTC_INTERNAL_PORT_TYPE_ELOOP == p_port_assign->type)
                || (CTC_INTERNAL_PORT_TYPE_ILOOP_ELOOP == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_DISCARD == p_port_assign->type));

    if (SYS_USW_INTERNAL_PORT_OP_TYPE_SET == op_type)
    {
        if (CTC_INTERNAL_PORT_TYPE_ELOOP == p_port_assign->type)
        {
            ds_t ds;
            uint32 cmd = 0;
            uint8 is_bind = 0;
            cmd = DRV_IOR(DsDestPort_t, DRV_ENTRY_FLAG);
            sal_memset(&ds, 0, sizeof(ds_t));
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_port_assign->inter_port, cmd, &ds));
            is_bind = GetDsDestPort(V, portLoopbackIndex_f, &ds);
            egs_set = egs_set&&is_bind;
        }

        if (igs_set || egs_set)
        {
            SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Queue] Internal port in use \n");
            return CTC_E_IN_USE;
        }

        if ((CTC_INTERNAL_PORT_TYPE_FWD == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_ILOOP == p_port_assign->type)
            || (CTC_INTERNAL_PORT_TYPE_ILOOP_ELOOP == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_DISCARD == p_port_assign->type))
        {
            SYS_INTERNAL_PORT_SET(lchip, SYS_INTERNAL_PORT_DIR_IGS, p_port_assign->inter_port);
        }

        if(CTC_INTERNAL_PORT_TYPE_WLAN == p_port_assign->type)
        {
            SYS_INTERNAL_PORT_SET(lchip, SYS_INTERNAL_PORT_DIR_IGS, p_port_assign->inter_port);
            SYS_INTERNAL_PORT_SET(lchip, SYS_INTERNAL_PORT_DIR_IGS, p_port_assign->inter_port+1);
        }

        if ((CTC_INTERNAL_PORT_TYPE_FWD == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_ELOOP == p_port_assign->type)
            || (CTC_INTERNAL_PORT_TYPE_ILOOP_ELOOP == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_DISCARD == p_port_assign->type))
        {
            SYS_INTERNAL_PORT_SET(lchip, SYS_INTERNAL_PORT_DIR_EGS, p_port_assign->inter_port);
        }

    }
    else if (SYS_USW_INTERNAL_PORT_OP_TYPE_FREE == op_type)
    {
        if ((0 == igs_set) && (0 == egs_set))
        {
            SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Internal port] Internal port not in use \n");
            return CTC_E_NOT_EXIST;
        }
    
        if((CTC_INTERNAL_PORT_TYPE_FWD == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_ILOOP == p_port_assign->type) 
            || (CTC_INTERNAL_PORT_TYPE_ILOOP_ELOOP == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_DISCARD == p_port_assign->type))
        {
            SYS_INTERNAL_PORT_UNSET(lchip, SYS_INTERNAL_PORT_DIR_IGS, p_port_assign->inter_port);
        }

        if(CTC_INTERNAL_PORT_TYPE_WLAN == p_port_assign->type)
        {
            SYS_INTERNAL_PORT_UNSET(lchip, SYS_INTERNAL_PORT_DIR_IGS, p_port_assign->inter_port);
            SYS_INTERNAL_PORT_UNSET(lchip, SYS_INTERNAL_PORT_DIR_IGS, p_port_assign->inter_port+1);
        }

        if((CTC_INTERNAL_PORT_TYPE_FWD == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_ELOOP == p_port_assign->type)
            || (CTC_INTERNAL_PORT_TYPE_ILOOP_ELOOP == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_DISCARD == p_port_assign->type))
        {
            SYS_INTERNAL_PORT_UNSET(lchip, SYS_INTERNAL_PORT_DIR_EGS, p_port_assign->inter_port);
        }
    }
    else if (SYS_USW_INTERNAL_PORT_OP_TYPE_ALLOC == op_type)
    {
        /* SYS_INTERNAL_PORT_START means sys drv internal port start */
        for (lport = SYS_INTERNAL_PORT_START; lport < (SYS_INTERNAL_PORT_START + SYS_INTERNAL_PORT_NUM); lport++)
        {
            igs_set = ((SYS_INTERNAL_PORT_ISSET(lchip, SYS_INTERNAL_PORT_DIR_IGS, SYS_MAP_DRV_LPORT_TO_SYS_LPORT(lport))
                      && ((CTC_INTERNAL_PORT_TYPE_FWD == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_ILOOP == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_DISCARD == p_port_assign->type)
                      || (CTC_INTERNAL_PORT_TYPE_WLAN == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_ILOOP_ELOOP == p_port_assign->type))) || (SYS_INTERNAL_PORT_ISSET(lchip, SYS_INTERNAL_PORT_DIR_IGS, SYS_MAP_DRV_LPORT_TO_SYS_LPORT(lport+1))
                      && (CTC_INTERNAL_PORT_TYPE_WLAN == p_port_assign->type)));

            egs_set = SYS_INTERNAL_PORT_ISSET(lchip, SYS_INTERNAL_PORT_DIR_EGS, SYS_MAP_DRV_LPORT_TO_SYS_LPORT(lport))
                      && ((CTC_INTERNAL_PORT_TYPE_FWD == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_ELOOP == p_port_assign->type)
                      || (CTC_INTERNAL_PORT_TYPE_ILOOP_ELOOP == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_DISCARD == p_port_assign->type));


            if (igs_set || egs_set)
            {
                continue;
            }
            else
            {
                break;
            }
        }

        if ((SYS_INTERNAL_PORT_START + SYS_INTERNAL_PORT_NUM) == lport)
        {
            SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Queue] Internal port no free count \n");
			return CTC_E_NO_RESOURCE;

        }

        p_port_assign->inter_port = SYS_MAP_DRV_LPORT_TO_SYS_LPORT(lport);

        if((CTC_INTERNAL_PORT_TYPE_FWD == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_ILOOP == p_port_assign->type)
            || (CTC_INTERNAL_PORT_TYPE_ILOOP_ELOOP == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_DISCARD == p_port_assign->type))
        {
            SYS_INTERNAL_PORT_SET(lchip, SYS_INTERNAL_PORT_DIR_IGS, SYS_MAP_DRV_LPORT_TO_SYS_LPORT(lport));
        }

        if(CTC_INTERNAL_PORT_TYPE_WLAN == p_port_assign->type)
        {
            SYS_INTERNAL_PORT_SET(lchip, SYS_INTERNAL_PORT_DIR_IGS, SYS_MAP_DRV_LPORT_TO_SYS_LPORT(lport));
            SYS_INTERNAL_PORT_SET(lchip, SYS_INTERNAL_PORT_DIR_IGS, SYS_MAP_DRV_LPORT_TO_SYS_LPORT(lport+1));
        }

        if((CTC_INTERNAL_PORT_TYPE_FWD == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_ELOOP == p_port_assign->type) 
            || (CTC_INTERNAL_PORT_TYPE_ILOOP_ELOOP == p_port_assign->type) || (CTC_INTERNAL_PORT_TYPE_DISCARD == p_port_assign->type))
        {
            SYS_INTERNAL_PORT_SET(lchip, SYS_INTERNAL_PORT_DIR_EGS, SYS_MAP_DRV_LPORT_TO_SYS_LPORT(lport));
        }
    }
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PORT, SYS_WB_APPID_INTERPORT_SUBID_USED, 1);
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_port_set_loop_port(uint8 lchip, ctc_internal_port_assign_para_t* p_port_assign, sys_nh_info_dsnh_t* p_dsnh_info, uint8 is_add)
{
    DsDestPortLoopback_m ds_dest_port_loopback;
    uint8 index = 0;
    uint32 cmd  = 0;
    uint32 field_val = 0;
    uint32 max_index = 0;
    uint16 lport = 0;
    uint32 nhid = 0;

    nhid = p_port_assign->nhid;
    lport = p_port_assign->inter_port;

    if (is_add && 0 == nhid)
    {
        return CTC_E_NONE;
    }

    if (is_add)
    {
        sys_usw_ftm_query_table_entry_num(lchip, DsDestPortLoopback_t, &max_index);

        /*get loopback index*/
        for (index = 0; index < max_index; index++)
        {
            cmd = DRV_IOR(DsDestPortLoopback_t, DRV_ENTRY_FLAG);
            sal_memset(&ds_dest_port_loopback, 0, sizeof(ds_dest_port_loopback));
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds_dest_port_loopback));

            if ((0 == GetDsDestPortLoopback(V, lbDestMap_f, &ds_dest_port_loopback))
               && (0 == GetDsDestPortLoopback(V, lbNextHopPtr_f, &ds_dest_port_loopback)))
            {
                break;
            }
        }

        if (max_index == index)
        {
            SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No resource in ASIC \n");
			return CTC_E_NO_RESOURCE;

        }

        field_val = BPE_EGS_MUXTYPE_LOOPBACK_ENCODE;
        cmd = DRV_IOW(DsDestPort_t, DsDestPort_muxPortType_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, SYS_MAP_SYS_LPORT_TO_DRV_LPORT(lport), cmd, &field_val));

        field_val = index;
        cmd = DRV_IOW(DsDestPort_t, DsDestPort_portLoopbackIndex_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, SYS_MAP_SYS_LPORT_TO_DRV_LPORT(lport), cmd, &field_val));

        sal_memset(&ds_dest_port_loopback, 0, sizeof(DsDestPortLoopback_m));

        SetDsDestPortLoopback(V, lbDestMap_f, &ds_dest_port_loopback, p_dsnh_info->dest_map);

        SetDsDestPortLoopback(V, lbNextHopPtr_f, &ds_dest_port_loopback, p_dsnh_info->dsnh_offset);
        SetDsDestPortLoopback(V, lbNextHopExt_f, &ds_dest_port_loopback, p_dsnh_info->nexthop_ext);

        if (DRV_FROM_TMM(lchip) && (SYS_NH_TYPE_ILOOP != p_dsnh_info->nh_entry_type))
        {
            SetDsDestPortLoopback(V, lbBypassIpe_f, &ds_dest_port_loopback, 1);
        }

        if (CTC_FLAG_ISSET(p_port_assign->flag, CTC_INTERNAL_PORT_FLAG_USE_LOGIC_DST_PORT))
        {
            SetDsDestPortLoopback(V, lbLogicPortInHeader_f, &ds_dest_port_loopback, 1);
        }

        cmd = DRV_IOW(DsDestPortLoopback_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds_dest_port_loopback));
    }
    else
    {
        field_val = BPE_EGS_MUXTYPE_NOMUX;
        cmd = DRV_IOW(DsDestPort_t, DsDestPort_muxPortType_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, SYS_MAP_SYS_LPORT_TO_DRV_LPORT(lport), cmd, &field_val));

        field_val = 0;
        cmd = DRV_IOR(DsDestPort_t, DsDestPort_portLoopbackIndex_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, SYS_MAP_SYS_LPORT_TO_DRV_LPORT(lport), cmd, &field_val));
        index = field_val;
        if (index != 0)
        {
            sal_memset(&ds_dest_port_loopback, 0, sizeof(DsDestPortLoopback_m));
            cmd = DRV_IOW(DsDestPortLoopback_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds_dest_port_loopback));
        }
        field_val = 0;
        cmd = DRV_IOW(DsDestPort_t, DsDestPort_portLoopbackIndex_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, SYS_MAP_SYS_LPORT_TO_DRV_LPORT(lport), cmd, &field_val));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_internal_port_set_bypass_epe(uint8 lchip, uint32 lport, uint8 bypass)
{
    uint32 cmd = 0;
    uint32 value[CTC_PORT_BITMAP_IN_WORD] = {0};

    cmd = DRV_IOR(EpeHeaderAdjustBypassCfg_t, EpeHeaderAdjustBypassCfg_bypassEpe_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    if (bypass)
    {
        CTC_BIT_SET(value[lport / 32], (lport % 32));
    }
    else
    {
        CTC_BIT_UNSET(value[lport / 32], (lport % 32));
    }

    cmd = DRV_IOW(EpeHeaderAdjustBypassCfg_t, EpeHeaderAdjustBypassCfg_bypassEpe_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    return CTC_E_NONE;
}


STATIC int32
_sys_usw_internal_port_set_bypass_ipe(uint8 lchip, uint32 lport, uint8 bypass)
{
    uint32 cmd = 0;
    uint32 value[CTC_PORT_BITMAP_IN_WORD] = {0};

    cmd = DRV_IOR(EpeHeaderAdjustBypassCfg_t, EpeHeaderAdjustBypassCfg_bypassIpe_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    if (bypass)
    {
        CTC_BIT_SET(value[lport / 32], (lport % 32));
    }
    else
    {
        CTC_BIT_UNSET(value[lport / 32], (lport % 32));
    }

    cmd = DRV_IOW(EpeHeaderAdjustBypassCfg_t, EpeHeaderAdjustBypassCfg_bypassIpe_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    return CTC_E_NONE;
}


STATIC int32
_sys_usw_internal_port_wlan_e2iloop_init(uint8 lchip)
{
    uint32 lport = 0;
    uint32 cmd = 0;
    QWriteDot1AeCtl_m dot1_ae_ctl;

    sal_memset(&dot1_ae_ctl, 0, sizeof(QWriteDot1AeCtl_m));
    cmd = DRV_IOR(QWriteDot1AeCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &dot1_ae_ctl));
    lport = SYS_RSV_PORT_WLAN_E2ILOOP;
    SetQWriteDot1AeCtl(V, e2iLoopPort_f, &dot1_ae_ctl, lport);
    cmd = DRV_IOW(QWriteDot1AeCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &dot1_ae_ctl));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_internal_port_ip_tunnel_init(uint8 lchip)
{
    uint8 gchip = 0;
    uint32 lport = 0;
    uint32 cmd = 0;
    uint16 interface_id = 0;
    DsSrcInterface_m src_interface;
    DsDestInterface_m dest_interface;
    DsDestPort_m dest_port;
    DsSrcPort_m src_port;
    DsPhyPortExt_m phy_port_ext;
    DsPhyPort_m phy_port;
    DsDestPortLoopback_m ds_dest_port_loopback;

    sys_usw_get_gchip_id(lchip, &gchip);
    lport = SYS_RSV_PORT_IP_TUNNEL;
    interface_id = MCHIP_CAP(SYS_CAP_L3IF_RSV_L3IF_ID);
    sal_memset(&src_interface, 0, sizeof(src_interface));
    SetDsSrcInterface(V, v4UcastEn_f, &src_interface, 1);
    SetDsSrcInterface(V, v4McastEn_f, &src_interface, 1);
    SetDsSrcInterface(V, v6UcastEn_f, &src_interface, 1);
    SetDsSrcInterface(V, v6McastEn_f, &src_interface, 1);
    SetDsSrcInterface(V, routeLookupMode_f, &src_interface, 1);
    SetDsSrcInterface(V, routeAllPackets_f, &src_interface, 1);
    cmd = DRV_IOW(DsSrcInterface_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, interface_id, cmd, &src_interface));

    sal_memset(&dest_interface, 0, sizeof(dest_interface));
    cmd = DRV_IOW(DsDestInterface_t, DRV_ENTRY_FLAG);
    SetDsDestInterface(V, mtuExceptionEn_f, &dest_interface, 1);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, interface_id, cmd, &dest_interface));

    sal_memset(&dest_port, 0, sizeof(dest_port));
    cmd = DRV_IOR(DsDestPort_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, cmd, &dest_port));
    SetDsDestPort(V, dot1QEn_f, &dest_port, 0);
    SetDsDestPort(V, defaultVlanId_f, &dest_port, 0);
    SetDsDestPort(V, muxPortType_f, &dest_port, 3);
    SetDsDestPort(V, portMappedInterfaceId_f, &dest_port, interface_id);

    cmd = DRV_IOW(DsDestPort_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, cmd, &dest_port));

    sal_memset(&src_port, 0, sizeof(src_port));
    cmd = DRV_IOR(DsSrcPort_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, cmd, &src_port));
    SetDsSrcPort(V, interfaceId_f, &src_port, interface_id);
    SetDsSrcPort(V, routedPort_f, &src_port, 1);
    SetDsSrcPort(V, addDefaultVlanDisable_f, &src_port, 1);
    cmd = DRV_IOW(DsSrcPort_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, cmd, &src_port));

    sal_memset(&phy_port_ext, 0, sizeof(phy_port_ext));
    cmd = DRV_IOR(DsPhyPortExt_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, cmd, &phy_port_ext));
    SetDsPhyPortExt(V, defaultVlanId_f, &phy_port_ext, 0);
    cmd = DRV_IOW(DsPhyPortExt_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, cmd, &phy_port_ext));

    sal_memset(&phy_port, 0, sizeof(phy_port));
    SetDsPhyPort(V, fwdHashGenDis_f, &phy_port, 1);
    cmd = DRV_IOW(DsPhyPort_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, cmd, &phy_port));


    /*enable eloop for port*/
    sal_memset(&ds_dest_port_loopback, 0, sizeof(ds_dest_port_loopback));
    cmd = DRV_IOR(DsDestPortLoopback_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds_dest_port_loopback)); /* LoopbackEncode */
    if (DRV_FROM_AT(lchip))
    {
        SetDsDestPortLoopback(V, lbNextHopPtr_f, &ds_dest_port_loopback, (lport&0xFF)|((lport >> 8) << 14));
    }
    else if (DRV_FROM_TMM(lchip))
    {
        SetDsDestPortLoopback(V, lbNextHopPtr_f, &ds_dest_port_loopback, lport);
    }
    else
    {
        SetDsDestPortLoopback(V, lbDestMap_f, &ds_dest_port_loopback, SYS_ENCODE_DESTMAP(gchip, SYS_RSV_PORT_ILOOP_ID));
        SetDsDestPortLoopback(V, lbNextHopPtr_f, &ds_dest_port_loopback, ((((lport & 0x80) >> 7) << 16) | (lport & 0x7F)));
    }
    cmd = DRV_IOW(DsDestPortLoopback_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds_dest_port_loopback));

    /*eloop default enable loopback to iloop port*/
    lport = SYS_RSV_PORT_ELOOP_ID;
    sal_memset(&dest_port, 0, sizeof(dest_port));
    cmd = DRV_IOR(DsDestPort_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, cmd, &dest_port));
    SetDsDestPort(V, dot1QEn_f, &dest_port, 0);
    SetDsDestPort(V, defaultVlanId_f, &dest_port, 0);
    SetDsDestPort(V, muxPortType_f, &dest_port, 3);
    cmd = DRV_IOW(DsDestPort_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, cmd, &dest_port));

    return CTC_E_NONE;
}

#define __________EXTERNAL_FUNCTION___________
/*loop mode:2, need to alloc two eloop ports*/
int32
_sys_usw_internal_port_eloop_port(uint8 lchip, uint8 enable)
{
    int32 ret = CTC_E_NONE;
    uint8 pp_id = 0;
    uint8 gchip_id = 0;
    uint16 chan_id = 0;
    ctc_internal_port_assign_para_t port_assign_dp0;
    ctc_internal_port_assign_para_t port_assign_dp1;
    sys_port_chan_map_param_t chan_map_param;

    chan_map_param.is_pp = 0;
    sys_usw_get_gchip_id(lchip, &gchip_id);
    sal_memset(&port_assign_dp0, 0, sizeof(port_assign_dp0));
    port_assign_dp0.type = CTC_INTERNAL_PORT_TYPE_ELOOP;
    port_assign_dp0.gchip = gchip_id;

    sal_memset(&port_assign_dp1, 0, sizeof(port_assign_dp1));
    port_assign_dp1.type = CTC_INTERNAL_PORT_TYPE_ELOOP;
    port_assign_dp1.gchip = gchip_id;

    if (DRV_FROM_AT(lchip))
    {
        if (enable)
        {
            uint8 pp_num = SYS_PP_NUM(lchip);
            for (pp_id = 0; pp_id < pp_num; pp_id++)
            {
                sal_memset(&port_assign_dp0, 0, sizeof(port_assign_dp0));
                port_assign_dp0.type = CTC_INTERNAL_PORT_TYPE_ELOOP;
                port_assign_dp0.gchip = gchip_id;
                port_assign_dp0.pp_id = pp_id;
                CTC_ERROR_RETURN(_sys_usw_internal_port_allocate(lchip, &port_assign_dp0, NULL));
                chan_id = MCHIP_CAP(SYS_CAP_CHANID_ELOOP)+2*pp_id+1;
                port_assign_dp0.type = CTC_INTERNAL_PORT_TYPE_FWD;
                chan_map_param.lport = port_assign_dp0.inter_port;
                chan_map_param.channel_id = chan_id;
                CTC_ERROR_GOTO(_sys_usw_internal_port_set_channel(lchip, &chan_map_param, port_assign_dp0.type, 1), ret, roll_back_2);
                inter_port_master[lchip]->eloop_port[2*pp_id+1] = port_assign_dp0.inter_port;
            }
        }
        else
        {
            for (pp_id = 0; pp_id < SYS_PP_NUM(lchip); pp_id++)
            {
                port_assign_dp0.inter_port = inter_port_master[lchip]->eloop_port[2*pp_id+1];
                inter_port_master[lchip]->eloop_port[2*pp_id+1] = inter_port_master[lchip]->eloop_port[2*pp_id];
                _sys_usw_internal_port_release(lchip, &port_assign_dp0);
            }
        }
    }
    else
    {
        if (enable)
        {
            CTC_ERROR_RETURN(_sys_usw_internal_port_allocate(lchip, &port_assign_dp0, NULL));
            chan_id = MCHIP_CAP(SYS_CAP_CHANID_ELOOP)+2;
            port_assign_dp0.type = CTC_INTERNAL_PORT_TYPE_FWD;
            chan_map_param.lport = port_assign_dp0.inter_port;
            chan_map_param.channel_id = chan_id;
            CTC_ERROR_GOTO(_sys_usw_internal_port_set_channel(lchip, &chan_map_param, port_assign_dp0.type, 1), ret, roll_back_0);
            inter_port_master[lchip]->eloop_port[2] = port_assign_dp0.inter_port;
            CTC_ERROR_GOTO(_sys_usw_internal_port_allocate(lchip, &port_assign_dp1, NULL), ret, roll_back_0);
            chan_id = MCHIP_CAP(SYS_CAP_CHANID_ELOOP)+2+MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM);
            port_assign_dp1.type = CTC_INTERNAL_PORT_TYPE_FWD;
            chan_map_param.lport = port_assign_dp1.inter_port;
            chan_map_param.channel_id = chan_id;
            CTC_ERROR_GOTO(_sys_usw_internal_port_set_channel(lchip, &chan_map_param, port_assign_dp1.type, 1), ret, roll_back_1);
            inter_port_master[lchip]->eloop_port[3] = port_assign_dp1.inter_port;
        }
        else
        {
            port_assign_dp1.inter_port = inter_port_master[lchip]->eloop_port[3];
            inter_port_master[lchip]->eloop_port[3] = SYS_RSV_PORT_ELOOP1_ID;
            _sys_usw_internal_port_release(lchip, &port_assign_dp1);
            port_assign_dp0.inter_port = inter_port_master[lchip]->eloop_port[2];
            inter_port_master[lchip]->eloop_port[2] = SYS_RSV_PORT_ELOOP_ID;
            _sys_usw_internal_port_release(lchip, &port_assign_dp0);
        }
    }

    return CTC_E_NONE;
roll_back_2:
    for(; pp_id>0; pp_id--)
    {
        port_assign_dp0.inter_port = inter_port_master[lchip]->eloop_port[2*pp_id+1];
        inter_port_master[lchip]->eloop_port[2*pp_id+1] = inter_port_master[lchip]->eloop_port[2*pp_id];
        _sys_usw_internal_port_release(lchip, &port_assign_dp0);
    }
roll_back_1:
    if (!DRV_FROM_AT(lchip))
    {
        _sys_usw_internal_port_release(lchip, &port_assign_dp1);
    }
roll_back_0:
    if (DRV_FROM_AT(lchip))
    {
        port_assign_dp0.inter_port = inter_port_master[lchip]->eloop_port[1];
        inter_port_master[lchip]->eloop_port[1] = inter_port_master[lchip]->eloop_port[0];
    }
    _sys_usw_internal_port_release(lchip, &port_assign_dp0);
    return ret;
}

/**
 @brief Set internal port for special usage, for example, I-Loop, E-Loop.
*/
int32
_sys_usw_internal_port_set(uint8 lchip, ctc_internal_port_assign_para_t* p_port_assign, sys_nh_info_dsnh_t* p_dsnh_info)
{
    uint16 dst_drv_lport = 0;
    uint16 interal_drv_lport = 0;
    uint32 chan_id = 0;
    int32 ret = CTC_E_NONE;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    sys_port_chan_map_param_t chan_map_param;

    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    if (p_port_assign->type == CTC_INTERNAL_PORT_TYPE_FWD)
    {
        SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_port_assign->fwd_gport, lchip, dst_drv_lport);
    }

    interal_drv_lport = SYS_MAP_SYS_LPORT_TO_DRV_LPORT(p_port_assign->inter_port);

    CTC_VALUE_RANGE_CHECK(interal_drv_lport, SYS_INTERNAL_PORT_START, (SYS_INTERNAL_PORT_START + SYS_INTERNAL_PORT_NUM - 1));

    CTC_ERROR_RETURN(_sys_usw_port_set_port_bitmap(lchip, p_port_assign, SYS_USW_INTERNAL_PORT_OP_TYPE_SET));

    if (p_port_assign->type == CTC_INTERNAL_PORT_TYPE_FWD)
    {
        dmps_port_info.gport = p_port_assign->fwd_gport;
        /* notice gport is physical port can't get channel by SYS_GET_CHANNEL_ID api */
        CTC_ERROR_GOTO(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PHY_PORT_CHAN_ID, (void*)&chan_id),ret,error_pro);
    }
    else if (CTC_INTERNAL_PORT_TYPE_ELOOP == p_port_assign->type || CTC_INTERNAL_PORT_TYPE_ILOOP_ELOOP == p_port_assign->type)
    {
        uint32 pp_id = 0;
        CTC_ERROR_GOTO(_sys_usw_port_set_loop_port(lchip, p_port_assign, p_dsnh_info, 1), ret, error_pro);

        if (CTC_FLAG_ISSET(p_port_assign->flag, CTC_INTERNAL_PORT_DONT_CARE_PP_ID))
        {
            for (pp_id = 0; pp_id < SYS_PP_NUM(lchip); pp_id++)
            {
                chan_map_param.channel_id = MCHIP_CAP(SYS_CAP_CHANID_ELOOP)+ pp_id*2;
                chan_map_param.lport = p_port_assign->inter_port;
                chan_map_param.is_pp = 1;
                CTC_ERROR_GOTO(_sys_usw_internal_port_set_channel(lchip+pp_id, &chan_map_param, p_port_assign->type, 1),ret,error_pro);
            }
            return CTC_E_NONE;
        }
        else
        {
            pp_id = p_port_assign->pp_id;
            chan_id = MCHIP_CAP(SYS_CAP_CHANID_ELOOP) + pp_id*2;
        }
    }

    if ((p_port_assign->type != CTC_INTERNAL_PORT_TYPE_ILOOP)
        && (CTC_INTERNAL_PORT_TYPE_WLAN != p_port_assign->type) && (SYS_COMMON_USELESS_CHANNEL != chan_id))
    {
        chan_map_param.channel_id = chan_id;
        chan_map_param.lport = p_port_assign->inter_port;
        chan_map_param.is_pp = 0;
        CTC_ERROR_GOTO(_sys_usw_internal_port_set_channel(lchip, &chan_map_param, p_port_assign->type, 1),ret,error_pro);
    }
    return CTC_E_NONE;
error_pro:
    (void)_sys_usw_port_set_port_bitmap(lchip, p_port_assign, SYS_USW_INTERNAL_PORT_OP_TYPE_FREE);
    return ret;
}

/**
 @brief Allocate internal port for special usage, for example, I-Loop, E-Loop.
*/
int32
_sys_usw_internal_port_allocate(uint8 lchip, ctc_internal_port_assign_para_t* p_port_assign, sys_nh_info_dsnh_t* p_dsnh_info)
{
    uint32 chan_id = 0;
    uint32 cmd = 0;
    uint32 field_val = 0;
    uint16 internal_drv_lport = 0;
    uint16 dst_drv_lport = 0;
    int32 ret = CTC_E_NONE;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    sys_port_chan_map_param_t chan_map_param;
    
    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /*alloc a free internal port*/
    CTC_ERROR_RETURN(_sys_usw_port_set_port_bitmap(lchip, p_port_assign, SYS_USW_INTERNAL_PORT_OP_TYPE_ALLOC));

    internal_drv_lport = SYS_MAP_SYS_LPORT_TO_DRV_LPORT(p_port_assign->inter_port);

    if (CTC_INTERNAL_PORT_TYPE_FWD == p_port_assign->type)
    {
        SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_port_assign->fwd_gport, lchip, dst_drv_lport);

        dmps_port_info.gport = p_port_assign->fwd_gport;
        /* cfg src port disable stp */
        field_val = 1;
        cmd = DRV_IOW(DsSrcPort_t, DsSrcPort_stpDisable_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, internal_drv_lport, cmd, &field_val));

        /* cfg dest port disable stp */
        field_val = 0;
        cmd = DRV_IOW(DsDestPort_t, DsDestPort_stpCheckEn_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, internal_drv_lport, cmd, &field_val));

        CTC_ERROR_GOTO(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id),ret,error_pro);
    }
    else if (CTC_INTERNAL_PORT_TYPE_ELOOP == p_port_assign->type || CTC_INTERNAL_PORT_TYPE_ILOOP_ELOOP == p_port_assign->type)
    {
        uint32 pp_id = 0;
        if (CTC_FLAG_ISSET(p_port_assign->flag, CTC_INTERNAL_PORT_DONT_CARE_PP_ID))
        {
            for (pp_id = 0; pp_id < SYS_PP_NUM(lchip); pp_id++)
            {
                chan_map_param.channel_id = MCHIP_CAP(SYS_CAP_CHANID_ELOOP)+ pp_id*2;
                chan_map_param.lport = p_port_assign->inter_port;
                chan_map_param.is_pp = 1;
                CTC_ERROR_GOTO(_sys_usw_internal_port_set_channel(lchip+pp_id, &chan_map_param, p_port_assign->type, 1),ret,error_pro);
            }
            return CTC_E_NONE;
        }
        else
        {
            pp_id = p_port_assign->pp_id;
        }
        chan_id = MCHIP_CAP(SYS_CAP_CHANID_ELOOP)+ pp_id*2;
        CTC_ERROR_GOTO(_sys_usw_port_set_loop_port(lchip, p_port_assign, p_dsnh_info, 1),ret,error_pro);
    }

    if ((p_port_assign->type != CTC_INTERNAL_PORT_TYPE_ILOOP)
        && (CTC_INTERNAL_PORT_TYPE_WLAN != p_port_assign->type) && (SYS_COMMON_USELESS_CHANNEL != chan_id))
    {
        chan_map_param.channel_id = chan_id;
        chan_map_param.lport = p_port_assign->inter_port;
        chan_map_param.is_pp = 0;
        CTC_ERROR_GOTO(_sys_usw_internal_port_set_channel(lchip, &chan_map_param, p_port_assign->type, 1),ret,error_pro);
    }
    return CTC_E_NONE;
error_pro:
    (void)_sys_usw_port_set_port_bitmap(lchip, p_port_assign, SYS_USW_INTERNAL_PORT_OP_TYPE_FREE);
    return ret;
}

/**
 @brief Release internal port.
*/
int32
_sys_usw_internal_port_release(uint8 lchip, ctc_internal_port_assign_para_t* p_port_assign)
{
    uint32 chan_id = 0;
    uint16 internal_drv_lport = 0;
    uint16 dst_drv_lport = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    sys_port_chan_map_param_t chan_map_param;

    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    internal_drv_lport = SYS_MAP_SYS_LPORT_TO_DRV_LPORT(p_port_assign->inter_port);

    CTC_VALUE_RANGE_CHECK((internal_drv_lport), SYS_INTERNAL_PORT_START, (SYS_INTERNAL_PORT_START + SYS_INTERNAL_PORT_NUM - 1));
    if (CTC_INTERNAL_PORT_TYPE_FWD == p_port_assign->type)
    {
        SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_port_assign->fwd_gport, lchip, dst_drv_lport);
        dmps_port_info.gport = p_port_assign->fwd_gport;

        /* notice gport is physical port can't get channel by SYS_GET_CHANNEL_ID api */
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PHY_PORT_CHAN_ID, (void*)&chan_id));
    }

    if (p_port_assign->type == CTC_INTERNAL_PORT_TYPE_ELOOP ||p_port_assign->type == CTC_INTERNAL_PORT_TYPE_ILOOP_ELOOP)
    {
        CTC_ERROR_RETURN(_sys_usw_port_set_loop_port(lchip, p_port_assign, NULL, 0));
    }

    CTC_ERROR_RETURN(_sys_usw_port_set_port_bitmap(lchip, p_port_assign, SYS_USW_INTERNAL_PORT_OP_TYPE_FREE));

    if ((p_port_assign->type != CTC_INTERNAL_PORT_TYPE_ILOOP) 
        && (CTC_INTERNAL_PORT_TYPE_WLAN != p_port_assign->type) && (SYS_COMMON_USELESS_CHANNEL != chan_id))
    {
        chan_map_param.channel_id = chan_id;
        chan_map_param.lport = p_port_assign->inter_port;
        chan_map_param.is_pp = 0;
        CTC_ERROR_RETURN(_sys_usw_internal_port_set_channel(lchip, &chan_map_param, p_port_assign->type, 0));
    }

    return CTC_E_NONE;
}

#define ______API______

int32
sys_usw_internal_port_get_rsv_port(uint8 lchip, sys_internal_port_type_t type, uint32 dest_port, uint16* lport)
{
    int32 ret = CTC_E_NONE;

    SYS_INTERNAL_PORT_INIT_CHECK();
    CTC_PTR_VALID_CHECK(lport);

    SYS_PORT_LOCK(lchip);
    if (SYS_INTERNAL_PORT_TYPE_ELOOP == type)
    {
        uint32 eloop_port_idx = 0;

        if (DRV_FROM_AT(lchip))
        {
            uint32 pp_id = 0;
            sys_usw_dmps_port_info_t dmps_port_info = {0};
            dmps_port_info.gport = dest_port;
            ret = sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PP_ID, &pp_id);
            eloop_port_idx = (pp_id*2 + dest_port%2);
        }
        else
        {
            eloop_port_idx = inter_port_master[lchip]->eloop_port_cnt++;
        }
        *lport = inter_port_master[lchip]->eloop_port[eloop_port_idx%MCHIP_CAP(SYS_CAP_CHANID_LOOP_NUM)]; 
        SYS_PORT_UNLOCK(lchip);
        return ret;
    }
    *lport = inter_port_master[lchip]->inter_port[type];
    SYS_PORT_UNLOCK(lchip);

    return CTC_E_NONE;
}

int32
sys_usw_internal_port_set_overlay_property(uint8 lchip, uint16 lport)
{
    uint32 value = 1;
    uint32 cmd = 0;
    int32 ret = CTC_E_NONE;
    SYS_INTERNAL_PORT_INIT_CHECK();

    SYS_PORT_LOCK(lchip);
    cmd = DRV_IOW(DsPhyPortExt_t, DsPhyPortExt_nvgreEnable_f);
    ret = DRV_FIELD_IOCTL(lchip, lport, cmd, &value);
    SYS_PORT_UNLOCK(lchip);

    return ret;
}

int32
sys_usw_internal_port_eloop_port(uint8 lchip, uint8 enable)
{
    int32 ret = CTC_E_NONE;

    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_INTERNAL_PORT_INIT_CHECK();

    SYS_PORT_LOCK(lchip);
    ret = _sys_usw_internal_port_eloop_port(lchip, enable);
    SYS_PORT_UNLOCK(lchip);

    return ret;
}

int32
sys_usw_internal_port_get_loop_mode(uint8 lchip, uint8* val)
{
    uint32 cmd = 0;
    DsPortChannelLag_m port_chan_lag;
    uint32 eloop_port_idx = DRV_FROM_AT(lchip)?1:2;  /*arctic pp two loop channel*/

    SYS_PORT_LOCK(lchip);
    cmd = DRV_IOR(DsPortChannelLag_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, SYS_RSV_PORT_ELOOP_ID, cmd, &port_chan_lag);

    *val = 0;
    if (GetDsPortChannelLag(V, linkAggregationChannelGroup_f, &port_chan_lag))
    {
        *val = 1;
    }
    else if (inter_port_master[lchip]->eloop_port[eloop_port_idx] != SYS_RSV_PORT_ELOOP_ID)
    {
        *val = 2;
    }
    SYS_PORT_UNLOCK(lchip);

    return CTC_E_NONE;
}


int32
sys_usw_internal_port_set(uint8 lchip, ctc_internal_port_assign_para_t* p_port_assign)
{
    int32 ret = CTC_E_NONE;
    sys_nh_info_dsnh_t dsnh_info;

    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_INTERNAL_PORT_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_port_assign);
    CTC_MAX_VALUE_CHECK(p_port_assign->type, CTC_INTERNAL_PORT_TYPE_WLAN);
    CTC_MAX_VALUE_CHECK(p_port_assign->pp_id, SYS_PP_NUM(lchip));

    if (TRUE != sys_usw_chip_is_local(lchip, p_port_assign->gchip))
    {
        return CTC_E_INVALID_PARAM;
    }


    if (p_port_assign->nhid)
    {
        sal_memset(&dsnh_info, 0, sizeof(dsnh_info));
        CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, p_port_assign->nhid, &dsnh_info, 0));
    }

    SYS_PORT_LOCK(lchip);
    ret = _sys_usw_internal_port_set(lchip, p_port_assign, &dsnh_info);
    SYS_PORT_UNLOCK(lchip);

    return ret;
}

int32
sys_usw_internal_port_allocate(uint8 lchip, ctc_internal_port_assign_para_t* p_port_assign)
{
    int32 ret = CTC_E_NONE;
    sys_nh_info_dsnh_t dsnh_info;

    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_INTERNAL_PORT_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_port_assign);
    CTC_MAX_VALUE_CHECK(p_port_assign->type, CTC_INTERNAL_PORT_TYPE_WLAN);
    CTC_MAX_VALUE_CHECK(p_port_assign->pp_id, SYS_PP_NUM(lchip));

    if (TRUE != sys_usw_chip_is_local(lchip, p_port_assign->gchip))
    {
        return CTC_E_INVALID_PARAM;
    }

    if (p_port_assign->nhid)
    {
        sal_memset(&dsnh_info, 0, sizeof(dsnh_info));
        CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, p_port_assign->nhid, &dsnh_info, 0));
    }

    SYS_PORT_LOCK(lchip);
    ret = _sys_usw_internal_port_allocate(lchip, p_port_assign, &dsnh_info);
    SYS_PORT_UNLOCK(lchip);

    return ret;
}

int32
sys_usw_internal_port_release(uint8 lchip, ctc_internal_port_assign_para_t* p_port_assign)
{
    int32 ret = CTC_E_NONE;

    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_INTERNAL_PORT_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_port_assign);
    CTC_MAX_VALUE_CHECK(p_port_assign->type, CTC_INTERNAL_PORT_TYPE_WLAN);
    CTC_MAX_VALUE_CHECK(p_port_assign->inter_port, SYS_USW_MAX_PORT_NUM_PER_CHIP-1);

    if (TRUE != sys_usw_chip_is_local(lchip, p_port_assign->gchip))
    {
        return CTC_E_INVALID_PARAM;
    }

    SYS_PORT_LOCK(lchip);
    ret = _sys_usw_internal_port_release(lchip, p_port_assign);
    SYS_PORT_UNLOCK(lchip);

    return ret;
}

int32
sys_usw_internal_port_show(uint8 lchip)
{
    uint16 loop = 0;
    char port_type[SYS_INTERNAL_PORT_TYPE_MAX][16] = {"ILOOP", "ILOOP1", "ELOOP", "ELOOP1", "DROP", "IP_TUNNEL", "MIRROR", "WLAN_ENCAP", "WLAN_E2ILOOP", "HMAC",
                                                      "E2ILOOP", "EUNIT0", "EUNIT1", "TO_CPU", "MOD_ID", "BYPASS_IPE", "OAM_CPU", "OAM_CPU1", "SPINE_LEAF"};
    char dir_name[SYS_INTERNAL_PORT_DIR_MAX][16] = {"Ingress", "Egress"};
    char* port_list = NULL;
    uint16 len = 0;
    uint8 dir = 0;

    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_INTERNAL_PORT_INIT_CHECK();

    port_list = (char*)mem_malloc(MEM_PORT_MODULE, sizeof(char)*1024);
    if (NULL == port_list)
    {
        return CTC_E_NO_MEMORY;
    }

    SYS_PORT_LOCK(lchip);
    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\nInternal Rsv Port(%d~%d)\n", SYS_RSV_PORT_START, SYS_RSV_PORT_END);
    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "--------------------------\n");
    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-16s%s\n", "Type", "Port");
    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "--------------------------\n");
    for (loop = SYS_INTERNAL_PORT_TYPE_MIN; loop < SYS_INTERNAL_PORT_TYPE_MAX; loop++)
    {
        if(0 == inter_port_master[lchip]->inter_port[loop])
        {
            continue;
        }
        if (DRV_FROM_AT(lchip) &&
            ((SYS_INTERNAL_PORT_TYPE_ILOOP == loop) || (SYS_INTERNAL_PORT_TYPE_ELOOP == loop)))
        {
            SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-16s%d ~ %d\n", port_type[loop], (inter_port_master[lchip]->inter_port[loop] - SYS_PP_NUM(lchip) + 1),
                inter_port_master[lchip]->inter_port[loop]);
        }
        else
        {
            SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-16s%d\n", port_type[loop], inter_port_master[lchip]->inter_port[loop]);
        }
    }

    if (((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)) && MCHIP_CAP(SYS_CAP_XPIPE_PORT_NUM)) || DRV_IS_TSINGMA(lchip))
    {
        SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-16s%d\n", "XPIPE_RSV", SYS_USW_XPIPE_RSV_PORT);
    }

    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\nInternal Used Port(%d~%d)\n", SYS_INTERNAL_PORT_START, SYS_INTERNAL_PORT_END);
    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-----------------------------------------------------\n");
    sal_memset(port_list, 0, sizeof(char)*1024);
    for (dir = SYS_INTERNAL_PORT_DIR_IGS; dir < SYS_INTERNAL_PORT_DIR_MAX; dir++)
    {
        len = 0;
        for (loop = SYS_INTERNAL_PORT_START; loop < (SYS_INTERNAL_PORT_START + SYS_INTERNAL_PORT_NUM); loop++)
        {
            if (SYS_INTERNAL_PORT_ISSET(lchip, dir, SYS_MAP_DRV_LPORT_TO_SYS_LPORT(loop)))
            {
                if (((loop == SYS_INTERNAL_PORT_START)
                    && !SYS_INTERNAL_PORT_ISSET(lchip, dir, SYS_MAP_DRV_LPORT_TO_SYS_LPORT(loop+1)))
                    || (loop == (SYS_INTERNAL_PORT_START + SYS_INTERNAL_PORT_NUM - 1))
                    || !SYS_INTERNAL_PORT_ISSET(lchip, dir, SYS_MAP_DRV_LPORT_TO_SYS_LPORT(loop+1)))
                {
                    len += sal_sprintf(port_list + len, "%d ", loop);
                }
                else if (((loop == SYS_INTERNAL_PORT_START)
                        && SYS_INTERNAL_PORT_ISSET(lchip, dir, SYS_MAP_DRV_LPORT_TO_SYS_LPORT(loop+1)))
                        || !SYS_INTERNAL_PORT_ISSET(lchip, dir, SYS_MAP_DRV_LPORT_TO_SYS_LPORT(loop-1)))
                {
                    len += sal_sprintf(port_list + len, "%d-", loop);
                }
            }
        }

        if (len)
        {
            SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-8s: %s\n", dir_name[dir], port_list);
        }
    }
    SYS_PORT_UNLOCK(lchip);

    mem_free(port_list);
    
    return CTC_E_NONE;
}

int32 sys_usw_internal_port_wb_sync(uint8 lchip,uint32 app_id)
{
    uint16 idx1 = 0;
    uint16 idx2 = 0;
    int32 ret = CTC_E_NONE;
    uint32  max_entry_cnt = 0;
    ctc_wb_data_t wb_data ={0};
    sys_wb_interport_master_t* p_wb_inter_master = NULL;
    sys_wb_interport_used_t* p_wb_inter_used = NULL;

    CTC_WB_ALLOC_BUFFER(&wb_data.buffer);

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_INTERPORT_SUBID_MASTER)
    {
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_interport_master_t, CTC_FEATURE_PORT, SYS_WB_APPID_INTERPORT_SUBID_MASTER);

        p_wb_inter_master = (sys_wb_interport_master_t *)wb_data.buffer;
        /*mapping data*/
        p_wb_inter_master->lchip = lchip;
        p_wb_inter_master->version = SYS_WB_VERSION_INTER_PORT;
        wb_data.valid_cnt = 1;
        CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_PORT, SYS_WB_APPID_INTERPORT_SUBID_MASTER);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_INTERPORT_SUBID_USED)
    {
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_interport_used_t, CTC_FEATURE_PORT, SYS_WB_APPID_INTERPORT_SUBID_USED);
        max_entry_cnt = wb_data.buffer_len/ (wb_data.key_len + wb_data.data_len);

        for (idx1 = 0; idx1 < SYS_INTERNAL_PORT_DIR_MAX; idx1++)
        {
            for (idx2 = 0; idx2 < (SYS_USW_MAX_PORT_NUM_PER_CHIP / BITS_NUM_OF_WORD); idx2++)
            {
                p_wb_inter_used = (sys_wb_interport_used_t *)wb_data.buffer + idx1 * (SYS_USW_MAX_PORT_NUM_PER_CHIP / BITS_NUM_OF_WORD) + idx2;
                p_wb_inter_used->idx1 = idx1;
                p_wb_inter_used->idx2 = idx2;
                p_wb_inter_used->used = inter_port_master[lchip]->is_used[idx1][idx2];
                if (++wb_data.valid_cnt == max_entry_cnt)
                {
                    CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
                    wb_data.valid_cnt = 0;
                }
            }
        }
        if (wb_data.valid_cnt)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_PORT, SYS_WB_APPID_INTERPORT_SUBID_USED);
    }

done:
     CTC_WB_FREE_BUFFER(wb_data.buffer);

    return ret;
}

int32 sys_usw_internal_port_wb_restore(uint8 lchip)
{
    int32 ret = CTC_E_NONE;
    uint32 entry_cnt = 0;
    ctc_wb_query_t    wb_query;
    sys_wb_interport_master_t  wb_inter_master = {0};
    sys_wb_interport_used_t  wb_inter_used = {0};
    uint16 lport = 0;
    uint16 chan_id = 0;
    uint8 idx = 0;

    CTC_WB_ALLOC_BUFFER(&wb_query.buffer);

    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_interport_master_t, CTC_FEATURE_PORT, SYS_WB_APPID_INTERPORT_SUBID_MASTER);

    CTC_ERROR_GOTO(ctc_wb_query_entry(&wb_query), ret, done);

    if (wb_query.valid_cnt != 1 || wb_query.is_end != 1)
    {
        ret = wb_query.valid_cnt ? CTC_E_INVALID_CONFIG : CTC_E_NONE;
        goto done;
    }

    sal_memcpy((uint8*)&wb_inter_master, (uint8*)wb_query.buffer, wb_query.key_len + wb_query.data_len);

    if (CTC_WB_VERSION_CHECK(SYS_WB_VERSION_INTER_PORT, wb_inter_master.version))
    {
        ret = CTC_E_VERSION_MISMATCH;
        goto done;
    }

    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_interport_used_t, CTC_FEATURE_PORT, SYS_WB_APPID_INTERPORT_SUBID_USED);

    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        sal_memcpy((uint8*)&wb_inter_used, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);
        entry_cnt++;
        inter_port_master[lchip]->is_used[wb_inter_used.idx1][wb_inter_used.idx2] = wb_inter_used.used;
        if (DRV_FROM_TMM(lchip) && (SYS_INTERNAL_PORT_DIR_EGS == wb_inter_used.idx1))
        {
            for (idx=0; idx<BITS_NUM_OF_WORD; idx++)
            {
                if (!CTC_IS_BIT_SET(wb_inter_used.used, idx))
                {
                    continue;
                }
                lport = SYS_INTERNAL_PORT_GET(lchip, wb_inter_used.idx2, idx);
                sys_usw_get_channel_by_port(lchip, lport, &chan_id);
                if (DRV_FROM_AT(lchip) && (chan_id > MCHIP_CAP(SYS_CAP_CHANID_ELOOP))
                    && (chan_id > MCHIP_CAP(SYS_CAP_CHANID_ELOOP)+MCHIP_CAP(SYS_CAP_CHANID_LOOP_NUM)) && chan_id %2 == 1)
                {
                    inter_port_master[lchip]->eloop_port[chan_id-MCHIP_CAP(SYS_CAP_CHANID_ELOOP)] = lport;
                }
                else
                {
                    if (chan_id == (MCHIP_CAP(SYS_CAP_CHANID_ELOOP)+2))
                    {
                        inter_port_master[lchip]->eloop_port[2] = lport;
                    }
                    else if (chan_id == (MCHIP_CAP(SYS_CAP_CHANID_ELOOP)+2+MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM)))
                    {
                        inter_port_master[lchip]->eloop_port[3] = lport;
                    }
                }
                
                
            }
        }
    CTC_WB_QUERY_ENTRY_END((&wb_query));

done:
    CTC_WB_FREE_BUFFER(wb_query.buffer);

   return ret;
}

/**
 @brief Internal port initialization.
*/
int32
sys_usw_internal_port_init(uint8 lchip)
{
    int32 ret = CTC_E_NONE;
    uint8 chip_type = 0;
    uint8 pp_id = 0;
    uint8 port_type = 0;
    uint16 lport = 0;
    uint8 gchip = 0;
    uint16 index = 0;
    sys_internal_port_type_map_t scl_hash_type_map[SYS_INTERNAL_PORT_TYPE_MAX] =
    {
        /*port_id, chan_id, port_num, is_pp, bypass_ipe, bypass_epe, chip_bitmap(arctic/tsingma_gx/tsingma_mx/tsingma/duet2)*/
        {SYS_RSV_PORT_ILOOP_ID,        MCHIP_CAP(SYS_CAP_CHANID_ILOOP),SYS_PP_NUM(lchip),0,0,1, 0x1F},
        {SYS_RSV_PORT_ILOOP1_ID,       MCHIP_CAP(SYS_CAP_CHANID_ILOOP)+MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM),1,0,0,1, 0xF},
        {SYS_RSV_PORT_ELOOP_ID,        MCHIP_CAP(SYS_CAP_CHANID_ELOOP),SYS_PP_NUM(lchip),0,0,0, 0x1F},
        {SYS_RSV_PORT_ELOOP1_ID,       MCHIP_CAP(SYS_CAP_CHANID_ELOOP)+MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM),1,0,0,0, 0xF},
        {SYS_RSV_PORT_DROP_ID,         MCHIP_CAP(SYS_CAP_CHANID_DROP),1,0,0,0, 0x1F},
        {SYS_RSV_PORT_IP_TUNNEL,       MCHIP_CAP(SYS_CAP_CHANID_ELOOP),1,1,0,0, 0x1F},
        {SYS_RSV_PORT_MIRROR,          MCHIP_CAP(SYS_CAP_CHANID_ILOOP),1,0,0,0, 0x1F},
        {SYS_RSV_PORT_WLAN_ENCAP,      MCHIP_CAP(SYS_CAP_CHANID_ILOOP),1,0,0,0, 0x3},
        {SYS_RSV_PORT_WLAN_E2ILOOP,    MCHIP_CAP(SYS_CAP_CHANID_ILOOP),1,0,0,0, 0x3},
        {SYS_RSV_PORT_HMAC,            MCHIP_CAP(SYS_CAP_CHANID_ILOOP),1,0,0,1, 0x4},
        {SYS_RSV_PORT_E2ILOOP_ID,      MCHIP_CAP(SYS_CAP_CHANID_ILOOP),1,0,1,1, 0x1C},
        {SYS_RSV_PORT_EUNIT0_ID,       MCHIP_CAP(SYS_CAP_CHANID_EUNIT0),1,0,0,1, 0x1C},
        {SYS_RSV_PORT_EUNIT1_ID,       MCHIP_CAP(SYS_CAP_CHANID_EUNIT1),1,0,0,1, 0x1C},
        {SYS_RSV_PORT_TO_CPU,          MCHIP_CAP(SYS_CAP_CHANID_DMA_RX0),1,0,0,1, 0x1F},
        {SYS_RSV_PORT_MOD_ID,          SYS_COMMON_USELESS_CHANNEL,1,0,0,0, 0x18},
        {SYS_RSV_PORT_BYPASS_IPE_ID,   SYS_COMMON_USELESS_CHANNEL,1,0,1,0, 0x1F},
        {SYS_RSV_PORT_OAM_CPU_ID,      MCHIP_CAP(SYS_CAP_CHANID_OAM),1,0,0,1, 0x1F},
        {SYS_RSV_PORT_OAM_CPU1_ID,     MCHIP_CAP(SYS_CAP_CHANID_OAM1),1,0,0,1, 0x18},
        {SYS_RSV_PORT_SPINE_LEAF_PORT, SYS_COMMON_USELESS_CHANNEL,1,0,0,0, 0x1F},
    };

    LCHIP_CHECK(lchip);
    /* check init */
    if (NULL != inter_port_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_INIT(lchip, inter_port_master, CTC_FEATURE_PORT);

    MALLOC_POINTER(sys_inter_port_master_t, inter_port_master[lchip]);
    if (NULL == inter_port_master[lchip])
    {
        SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
		return CTC_E_NO_MEMORY;
    }
    sal_memset(inter_port_master[lchip], 0, sizeof(sys_inter_port_master_t));
    CTC_ERROR_GOTO(sys_usw_get_gchip_id(lchip, &gchip), ret, exit);
    /*1. init internal port db and store port info*/
    chip_type = drv_get_chip_type(lchip);
    for (port_type = SYS_INTERNAL_PORT_TYPE_MIN; port_type < SYS_INTERNAL_PORT_TYPE_MAX; port_type++)
    {
        if (!CTC_IS_BIT_SET(scl_hash_type_map[port_type].chip_bitmap, chip_type))
        {
            continue;
        }
        lport = SYS_MAP_SYS_LPORT_TO_DRV_LPORT(scl_hash_type_map[port_type].port_id);

        if (scl_hash_type_map[port_type].bypass_epe)
        {
            CTC_ERROR_GOTO(_sys_usw_internal_port_set_bypass_epe(lchip, scl_hash_type_map[port_type].port_id, 1), ret, exit);
        }
        if (scl_hash_type_map[port_type].bypass_ipe)
        {
            CTC_ERROR_GOTO(_sys_usw_internal_port_set_bypass_ipe(lchip, scl_hash_type_map[port_type].port_id, 1), ret, exit);
        }
        inter_port_master[lchip]->inter_port[port_type] = scl_hash_type_map[port_type].port_id;
        if(SYS_COMMON_USELESS_CHANNEL == scl_hash_type_map[port_type].chan_id)
        {
            continue;
        }
        if (0 == scl_hash_type_map[port_type].is_pp)
        {
            CTC_ERROR_GOTO(sys_usw_add_port_to_channel(lchip, lport, scl_hash_type_map[port_type].chan_id, 0), ret, exit);
        }
        else
        {
            for (pp_id = 0; pp_id < SYS_PP_NUM(lchip); pp_id++)
            {
                CTC_ERROR_GOTO(sys_usw_add_port_to_channel(lchip+pp_id, lport, scl_hash_type_map[port_type].chan_id+pp_id*2, 1),ret,exit);
            }
        }
    }

    /*2. iloop default set qos trust outer*/
    for(index=SYS_RSV_PORT_ILOOP_ID;index>=SYS_RSV_PORT_ILOOP1_ID; index--)
    {
        if (index == SYS_RSV_PORT_SPINE_LEAF_PORT)
        {
            continue;
        }
        (void)(sys_usw_port_set_property(lchip, CTC_MAP_LPORT_TO_GPORT(gchip, index), CTC_PORT_PROP_QOS_POLICY, CTC_QOS_TRUST_OUTER));
        CTC_ERROR_GOTO(_sys_usw_internal_port_set_bypass_epe(lchip, index, 1), ret, exit);
    }

    /*3. Rsv xpipe port*/
    if (DRV_FROM_TM(lchip))
    {
        uint16 intn_port_start = 0;
        ctc_port_scl_property_t scl_prop;
        extern int32 sys_usw_dmps_get_extport_start_id(uint8 lchip, uint16* p_lport_start);

        sal_memset(&scl_prop, 0, sizeof(ctc_port_scl_property_t));
        CTC_ERROR_GOTO(sys_usw_dmps_get_extport_start_id(lchip, &intn_port_start), ret, exit);
        SYS_INTERNAL_PORT_START = intn_port_start;
        if (((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)) && MCHIP_CAP(SYS_CAP_XPIPE_PORT_NUM)) || DRV_IS_TSINGMA(lchip))
        {
            lport = MCHIP_CAP(SYS_CAP_INTERNAL_PORT_END);
            scl_prop.scl_id = 0;
            scl_prop.hash_type = CTC_PORT_IGS_SCL_HASH_TYPE_PORT;
            scl_prop.use_logic_port_en = TRUE;
            scl_prop.direction = CTC_INGRESS;
            CTC_ERROR_GOTO(sys_usw_port_set_scl_property(lchip, CTC_MAP_LPORT_TO_GPORT(gchip, lport), &scl_prop), ret, exit);
            scl_prop.scl_id = 1;
            CTC_ERROR_GOTO(sys_usw_port_set_scl_property(lchip, CTC_MAP_LPORT_TO_GPORT(gchip, lport), &scl_prop), ret, exit);
            CTC_ERROR_GOTO(sys_usw_port_set_property(lchip, CTC_MAP_LPORT_TO_GPORT(gchip, lport), CTC_PORT_PROP_RAW_PKT_TYPE, CTC_PORT_RAW_PKT_NOP), ret, exit);
            CTC_ERROR_GOTO(sys_usw_port_set_property(lchip, CTC_MAP_LPORT_TO_GPORT(gchip, lport), CTC_PORT_PROP_ADD_DEFAULT_VLAN_DIS, 1), ret, exit);
            SYS_INTERNAL_PORT_END -= 1;
            SYS_RSV_PORT_START -= 1;
        }
    }

    /*4. wlan/ip_tunnel config hardware table*/
    if (!DRV_FROM_TMM(lchip))
    {
        CTC_ERROR_GOTO(_sys_usw_internal_port_wlan_e2iloop_init(lchip), ret, exit);
    }
    CTC_ERROR_GOTO(_sys_usw_internal_port_ip_tunnel_init(lchip), ret, exit);
    
    /*5. store eloop port to db*/
    if(DRV_FROM_AT(lchip))
    {
        for (pp_id = 0; pp_id < SYS_PP_NUM(lchip); pp_id++)
        {
            /*Eloop port init*/
            inter_port_master[lchip]->eloop_port[2*pp_id] = SYS_RSV_PORT_ELOOP_ID-pp_id;
            inter_port_master[lchip]->eloop_port[2*pp_id+1] = SYS_RSV_PORT_ELOOP_ID-pp_id;
        }
    }
    else
    {
        /*Eloop port init*/
        inter_port_master[lchip]->eloop_port[0] = SYS_RSV_PORT_ELOOP_ID;
        inter_port_master[lchip]->eloop_port[1] = SYS_RSV_PORT_ELOOP1_ID;
        inter_port_master[lchip]->eloop_port[2] = SYS_RSV_PORT_ELOOP_ID;
        inter_port_master[lchip]->eloop_port[3] = SYS_RSV_PORT_ELOOP1_ID;
    }

    /*6. warmboot restore*/
    if (CTC_WB_ENABLE(lchip) && (CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING))
    {
        CTC_ERROR_GOTO(sys_usw_internal_port_wb_restore(lchip), ret, exit);
    }
    return CTC_E_NONE;
exit:
    mem_free(inter_port_master[lchip]);
    return ret;
}

/**
 @brief Internal port initialization.
*/
int32
sys_usw_internal_port_deinit(uint8 lchip)
{
    LCHIP_CHECK(lchip);
    if (NULL == inter_port_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_DEINIT(lchip, inter_port_master, CTC_FEATURE_PORT);

    mem_free(inter_port_master[lchip]);
    return CTC_E_NONE;
}
